using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Life
{
    // Text control that automatically wraps text
    class TextArea : Control
    {
        private Color _color;
        private SpriteFont _font;

        private string _text;
        private string _wrappedText;
        private int _lineCount;
        private Vector2 _size;

        private int _maxWidth;

        public TextArea(string text, SpriteFont font, Color color, int maxWidth)
        {
            _text = text;
            _font = font;
            _color = color;
            _maxWidth = maxWidth;
        }

        // Text to draw
        public virtual string Text
        {
            get { return _text; }
            set
            {
                if (_text != value)
                {
                    _text = value;
                    InvalidateAutoSize();
                }
            }
        }


        /// <summary>
        /// Updates the text to fit within the screen width
        /// 
        /// TODO: input params instead of accessing member variables?
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        //private String parseText(String text)
        private void ComputeText()
        {
            String line = String.Empty;
            String[] wordArray = _text.Split(' ');

            _wrappedText = String.Empty;
            _lineCount = 0;

            foreach (String w in wordArray)
            {
                string word = w;

                // Break up words wider than available width
                while (line.Length == 0 && _font.MeasureString(word).X > _maxWidth)
                {
                    int len = FindMaxLength(word);
                    _wrappedText = word.Substring(0, len) + '\n';
                    word = word.Substring(len);
                    _lineCount++;
                }

                // Check if word will make line too long
                if (_font.MeasureString(line + word).X > _maxWidth)
                {
                    _wrappedText = _wrappedText + line + '\n';
                    line = String.Empty;
                    _lineCount++;
                }

                line = line + word + ' ';
            }

            if (line != String.Empty)
                _lineCount++;

            Vector2 rawSize = _font.MeasureString(_text);

            if (rawSize.X <= _maxWidth)
                _size = rawSize;
            else
                _size = new Vector2(_maxWidth, rawSize.Y * _lineCount);

            _wrappedText += line;
        }

        /// <summary>
        /// Find the maximum amount of a word that will fit in the screen width
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        private int FindMaxLength(string word)
        {
            int length = 1;
            string partialWord = String.Empty;

            do
            {
                partialWord = word.Substring(0, length);
                length++;
            } while (_font.MeasureString(partialWord).X <= _maxWidth);

            // Always return at least 1 char
            if (length > 2)
                length -= 2;
            else if (length > 1)
                length--;

            return length;
        }

        /// <summary>
        /// Calculates size of text area
        /// Should not be called if specific Size is specified
        /// </summary>
        /// <returns></returns>
        public override Vector2 ComputeSize()
        {
            ComputeText();

            return _size;
        }

        public override void Draw(DrawContext context)
        {
            context.SpriteBatch.DrawString(_font, _wrappedText, Position + context.DrawOffset, _color);
        }
    }
}
